package com.wowangz.cms.syscore.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.mongodb.DB;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;
import com.wowangz.cms.common.mongo.MongoDBManager;
import com.wowangz.cms.common.utils.DataFormat;
import com.wowangz.cms.common.utils.EncodeUtils;
import com.wowangz.cms.syscore.exception.ServiceException;

/**
 * Http与Servlet工具类.
 * 
 * @author leiyang3
 */
@SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
public class ServletUtils {

	// -- content-type 常量定义 --//
	public static final String TEXT_TYPE = "text/plain";
	public static final String JSON_TYPE = "application/json";
	public static final String XML_TYPE = "text/xml";
	public static final String HTML_TYPE = "text/html";
	public static final String JS_TYPE = "text/javascript";
	public static final String EXCEL_TYPE = "application/vnd.ms-excel";
	public static final String PDF_TYPE = "application/pdf";

	// -- header 定义 --//
	public static final String AUTHENTICATION_HEADER = "Authorization";

	public static final long ONE_YEAR_SECONDS = 60 * 60 * 24 * 365;

	final private static Logger logger = LoggerFactory.getLogger(ServletUtils.class);

	/**
	 * 设置客户端缓存过期时间 Header.
	 */
	public static void setExpiresHeader(HttpServletResponse response, long expiresSeconds) {
		// Http 1.0 header
		response.setDateHeader("Expires", System.currentTimeMillis() + expiresSeconds * 1000);
		// Http 1.1 header
		response.setHeader("Cache-Control", "private, max-age=" + expiresSeconds);
	}

	/**
	 * 设置客户端无缓存Header.
	 */
	public static void setNoCacheHeader(HttpServletResponse response) {
		// Http 1.0 header
		response.setDateHeader("Expires", 0);
		response.addHeader("Pragma", "no-cache");
		// Http 1.1 header
		response.setHeader("Cache-Control", "no-cache");
	}

	/**
	 * 设置LastModified Header.
	 */
	public static void setLastModifiedHeader(HttpServletResponse response, long lastModifiedDate) {
		response.setDateHeader("Last-Modified", lastModifiedDate);
	}

	/**
	 * 设置Etag Header.
	 */
	public static void setEtag(HttpServletResponse response, String etag) {
		response.setHeader("ETag", etag);
	}

	/**
	 * 根据浏览器If-Modified-Since Header, 计算文件是否已被修改.
	 * 
	 * 如果无修改, checkIfModify返回false ,设置304 not modify status.
	 * 
	 * @param lastModified
	 *            内容的最后修改时间.
	 */
	public static boolean checkIfModifiedSince(HttpServletRequest request, HttpServletResponse response, long lastModified) {
		long ifModifiedSince = request.getDateHeader("If-Modified-Since");
		if ((ifModifiedSince != -1) && (lastModified < ifModifiedSince + 1000)) {
			response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
			return false;
		}
		return true;
	}

	/**
	 * 根据浏览器 If-None-Match Header, 计算Etag是否已无效.
	 * 
	 * 如果Etag有效, checkIfNoneMatch返回false, 设置304 not modify status.
	 * 
	 * @param etag
	 *            内容的ETag.
	 */
	public static boolean checkIfNoneMatchEtag(HttpServletRequest request, HttpServletResponse response, String etag) {
		String headerValue = request.getHeader("If-None-Match");
		if (headerValue != null) {
			boolean conditionSatisfied = false;
			if (!"*".equals(headerValue)) {
				StringTokenizer commaTokenizer = new StringTokenizer(headerValue, ",");

				while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
					String currentToken = commaTokenizer.nextToken();
					if (currentToken.trim().equals(etag)) {
						conditionSatisfied = true;
					}
				}
			} else {
				conditionSatisfied = true;
			}

			if (conditionSatisfied) {
				response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
				response.setHeader("ETag", etag);
				return false;
			}
		}
		return true;
	}

	/**
	 * 设置让浏览器弹出下载对话框的Header.
	 * 
	 * @param fileName
	 *            下载后的文件名.
	 */
	public static void setFileDownloadHeader(HttpServletResponse response, String fileName) {
		try {
			// 中文文件名支持
			String encodedfileName = new String(fileName.getBytes(), "ISO8859-1");
			response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + "\"");
		} catch (UnsupportedEncodingException e) {
		}
	}

	/**
	 * 取得带相同前缀的Request Parameters.
	 * 
	 * 返回的结果Parameter名已去除前缀.
	 */
	public static Map getParametersStartingWith(HttpServletRequest request, String prefix) {
		Assert.notNull(request, "Request must not be null");
		Enumeration paramNames = request.getParameterNames();
		Map params = new TreeMap();
		if (prefix == null) {
			prefix = "";
		}
		while (paramNames != null && paramNames.hasMoreElements()) {
			String paramName = (String) paramNames.nextElement();
			if ("".equals(prefix) || paramName.startsWith(prefix)) {
				String unprefixed = paramName.substring(prefix.length());
				String[] values = request.getParameterValues(paramName);
				if (values == null || values.length == 0) {// NOSONAR
					// Do nothing, no values found at all.
				} else if (values.length > 1) {
					params.put(unprefixed, values);
				} else {
					params.put(unprefixed, values[0]);
				}
			}
		}
		return params;
	}

	/**
	 * 
	 * 在Spring
	 * MVC中使用非ajax请求并且表单提交时使用ServletUtils.getParametersToBaseEntity获取JavaBean
	 * 
	 * @param request
	 * @param className
	 * @return
	 * @throws ControllerException
	 */
	public static Object getParametersToBaseEntity(HttpServletRequest request, Class className) throws ServiceException {
		Assert.notNull(request, "Request must not be null");
		Object target = null;
		Field[] objFileds = className.getDeclaredFields();

		String paramName = null;
		String[] values = null;
		Object objValue = null;

		try {
			target = className.newInstance();

		} catch (InstantiationException e) {
			e.printStackTrace();
			throw new ServiceException(MessageResourcesUtils.getMessage(request, "messageAlertInfo.java.notinitialization"), e);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			throw new ServiceException(MessageResourcesUtils.getMessage(request, "messageAlertInfo.java.notinitialization"), e);
		}

		// 初始化JavaBean id
		paramName = "id";
		values = request.getParameterValues(paramName);
		if (values == null || values.length == 0) {
			// Do nothing, no values found at all.
		}
//		else if(StringUtils.isNumeric(String.valueOf(values[0]))){//id为纯数字字符串
//			if (!values[0].equals("")) {
//				// target.
//				Field idFidld = ReflectionUtils.getDeclaredField(target, paramName);
//				if (idFidld != null) {
//					ReflectionUtils.invokeSetterMethod(target, paramName, Long.valueOf(values[0]),Long.class);
//				}
//			}
//		}
		else {
			//id为混合字符串
			if (!values[0].equals("")) {
				// target.
				Field idFidld = ReflectionUtils.getDeclaredField(target, paramName);
				if (idFidld != null) {
					ReflectionUtils.invokeSetterMethod(target, paramName, values[0], String.class);
				}
			}
		}

		// 初始化JavaBean dataVersion
		paramName = "dataVersion";
		values = request.getParameterValues(paramName);
		if (values == null || values.length == 0) {
			// Do nothing, no values found at all.
		} else {
			if (!values[0].equals("")) {
				// target.
				Field idFidld = ReflectionUtils.getDeclaredField(target, paramName);
				if (idFidld != null) {
					ReflectionUtils.invokeSetterMethod(target, paramName, Long.valueOf(values[0]), Long.class);
				}
			}
		}

		if (objFileds != null && objFileds.length > 0) {

			for (int i = 0; i < objFileds.length; i++) {

				paramName = objFileds[i].getName();
				values = request.getParameterValues(paramName);

				if (values == null || values.length == 0) {
					// Do nothing, no values found at all.
				} else if (values[0].length() > 0 && !"".equals(values[0])) {
					// 做转码
					if (request.getMethod() != null && request.getMethod().equalsIgnoreCase("get")) {
						try {
							values[0] = new String(values[0].getBytes("ISO-8859-1"), "utf-8");
						} catch (UnsupportedEncodingException e1) {
							e1.printStackTrace();
						}
					}
					if (objFileds[i].getType().equals(long.class)) {
						objValue = Long.parseLong(values[0].trim());
					} else if (objFileds[i].getType().equals(Long.class)) {
						objValue = Long.valueOf(values[0].trim());
					} else if (objFileds[i].getType().equals(float.class)) {
						objValue = Float.parseFloat(values[0].trim());
					} else if (objFileds[i].getType().equals(Float.class)) {
						objValue = Float.valueOf(values[0].trim());
					} else if (objFileds[i].getType().equals(int.class)) {// int类型转换成int类型
						objValue = Integer.parseInt(values[0].trim());
					} else if (objFileds[i].getType().equals(Integer.class)) {
						objValue = Integer.valueOf(values[0].trim());
					} else if (objFileds[i].getType().equals(double.class)) {
						objValue = DataFormat.parseNumber(values[0].trim());
					} else if (objFileds[i].getType().equals(Double.class)) {
						objValue = Double.valueOf(DataFormat.parseNumber(values[0].trim()));
					} else if (objFileds[i].getType().equals(Timestamp.class)) {
						if (values[0].length() == DataFormat.getDateConvertString(DataFormat.DT_YYYY_MM_DD).length()) {
							objValue = DataFormat.parseTimestamp(values[0], DataFormat.DT_YYYY_MM_DD);
						} else if (values[0].length() == DataFormat.getDateConvertString(DataFormat.DT_YYYYMMDD_HHMMSS).length()) {
							objValue = DataFormat.parseTimestamp(values[0], DataFormat.DT_YYYYMMDD_HHMMSS);
						} else if (values[0].length() == DataFormat.getDateConvertString(DataFormat.DT_YYYYMMDD_HHMMSS_SSSS).length()) {
							objValue = DataFormat.parseTimestamp(values[0], DataFormat.DT_YYYYMMDD_HHMMSS);
						} else {
							throw new ServiceException(MessageResourcesUtils.getMessage(request, "messageAlertInfo.java.dateformaterror")
									+ values[0]);
						}
					} else if (objFileds[i].getType().equals(Date.class)) {
						if (values[0].length() == DataFormat.getDateConvertString(DataFormat.DT_YYYY_MM_DD).length()) {
							objValue = DataFormat.parseDate(values[0], DataFormat.DT_YYYY_MM_DD);
						} else {
							throw new ServiceException(MessageResourcesUtils.getMessage(request, "messageAlertInfo.java.dateformaterror")
									+ values[0]);
						}
					} else if (objFileds[i].getType().equals(boolean.class)) {
						if (values[0].equalsIgnoreCase("no") || values[0].equalsIgnoreCase("true")) {
							objValue = true;
						} else {
							objValue = false;
						}
					} else {
						objValue = values[0].trim();
					}
					try {
						logger.info("paramName :" + paramName + ",  paramValue :" + objValue);
						ReflectionUtils.setFieldValue(target, paramName, objValue);
						objValue = null;
					} catch (Exception e) {
						e.printStackTrace();
					}

				}
			}
		}

		return target;
	}

	/**
	 * 
	 * 在Spring
	 * MVC中使用非ajax请求并且表单提交时使用ServletUtils.getParametersToBaseEntity获取JavaBean
	 * 
	 * @param request
	 * @param className
	 * @return
	 * @throws ControllerException
	 */
	public static Object getMapToEntity(Map map, Class className) throws ServiceException {
		Object target = null;
		Field[] objFileds = className.getDeclaredFields();

		String paramName = null;
		Object values = null;
		Object objValue = null;

		try {
			target = className.newInstance();

		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		if (objFileds != null && objFileds.length > 0) {

			for (int i = 0; i < objFileds.length; i++) {

				paramName = objFileds[i].getName();
				values = map.get(paramName);
				if (values == null) {
					// Do nothing, no values found at all.
				} else {
					if (objFileds[i].getType().equals(Double.class)) {
						objValue = ((BigDecimal) (values)).doubleValue();
					} else {
						objValue = values;
					}
					try {
						logger.info("paramName :" + paramName + ",  paramValue :" + objValue);
						ReflectionUtils.setFieldValue(target, paramName, objValue);
						objValue = null;
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}

		return target;
	}

	/**
	 * 把HttpServletRequest Parameters 的值转换到HashMap中
	 * 
	 * @param request
	 * @return
	 * @throws ControllerException
	 */
	public static HashMap<String, Object> getParametersToHashMap(HttpServletRequest request) throws Exception {
		Assert.notNull(request, "Request must not be null");
		Enumeration paramEnum = request.getParameterNames();
		HashMap<String, Object> _paranMap = new HashMap();

		String _paramName = null;
		String[] _values = null;

		while (paramEnum.hasMoreElements()) {

			_paramName = paramEnum.nextElement().toString();
			_values = request.getParameterValues(_paramName);

			if (_values == null || _values.length == 0) {
				// Do nothing, no values found at all.
			} else if (_values.length == 1 && !_values[0].equals("")) {
				_paranMap.put(_paramName, _values[0]);
			} else if (_values.length > 1) {
				_paranMap.put(_paramName, _values);
			}
		}

		return _paranMap;
	}

	/**
	 * 对Http Basic验证的 Header进行编码.
	 */
	public static String encodeHttpBasic(String userName, String password) {
		String encode = userName + ":" + password;
		return "Basic " + EncodeUtils.base64Encode(encode.getBytes());
	}

	/**
	 * 
	 * 在Spring MVC中 enctype="multipart/form-data" 获取表单信息，上文件上传到ftp;
	 * 
	 * @param request
	 * @param className
	 * @return
	 * @throws ControllerException
	 */
	public static Map getMultipartFormDataToFTPFiles(HttpServletRequest request) throws ServiceException {

		return null;
	}

	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("X-Real-IP");
		if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getHeader("X-Forwarded-For");
		if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个IP值，第一个为真实IP。
			int index = ip.indexOf(',');
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		} else {
			return request.getRemoteAddr();
		}
	}
	/**
	 * 上传图片到mongoDB
	 * @Title: uploadMongodbfile 
	 * @Description: 
	 * @return String
	 * @author Green.Long
	 * @date 2016年8月29日 下午4:58:36
	 */
	public static String uploadMongodbfile(InputStream input, MongoDBManager manager, String databaseName) throws Exception {
		String pictureName = "";
		DB database = null;
		try {
			// 获得mongodb数据库
			database = manager.getDB(databaseName);
			GridFS gridFS = new GridFS(database);
			GridFSInputFile gridfsInputFile = gridFS.createFile(input);
			// 产生文件的序列
			String picSequence = UUID.randomUUID().toString().replace("-", "") + getRandomNumber();
			// 设置文件的mime类型
			gridfsInputFile.setContentType("image/jpeg");
			pictureName = picSequence + ".jpg";
			gridfsInputFile.setFilename(pictureName);
			// 保存文件
			gridfsInputFile.save();
			if (database.getLastError().ok()) {
				System.out.println("文件上传成功,文件名：" + pictureName);
			} else {
				throw new Exception("文件上传失败,文件名：" + pictureName);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw ex;
		} finally {
			if (database != null) {
				// 操作请求结束
				database.requestDone();
			}
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return pictureName;
	}

	/**
	 * 上传文件到mongoDB
	 * @Title: uploadAttachmentfile 
	 * @Description: 
	 * @return String
	 * @author Green.Long
	 * @date 2016年8月29日 下午5:03:06
	 */
	public static String uploadAttachmentfile(InputStream input, MongoDBManager manager, String databaseName) throws Exception {
		String pictureName = "";
		DB database = null;
		try {
			// 获得mongodb数据库
			database = manager.getDB(databaseName);
			GridFS gridFS = new GridFS(database);
			GridFSInputFile gridfsInputFile = gridFS.createFile(input);			
			// 产生文件的序列
			String picSequence = UUID.randomUUID().toString().replace("-", "") + getRandomNumber();
			// 设置文件的mime类型
			gridfsInputFile.setContentType("application/octet-stream");
			pictureName = picSequence;
			gridfsInputFile.setFilename(picSequence);
			System.err.println("文件名称：" + gridfsInputFile.getFilename());
			// 保存文件
			gridfsInputFile.save();
			if (database.getLastError().ok()) {
				System.out.println("文件上传成功,文件名：" + pictureName);
			} else {
				throw new Exception("文件上传失败,文件名：" + pictureName);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			logger.error("上传文件到mongoDB出错");
			throw ex;
		} finally {
			if (database != null) {
				// 操作请求结束
				database.requestDone();
			}
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					logger.info("关闭操作流出现异常");
					e.printStackTrace();
				}
			}
		}
		return pictureName;
	}
	
	/**
	 * @描述：获得一个随机数
	 * @author HUANGYUAN
	 * @TIME:2015年9月23日 下午4:00:21
	 * @return
	 */
	private static String getRandomNumber() {
		double random = Math.random();
		random = random * 10000;
		double floor = Math.floor(random);
		return String.valueOf((int)floor);
	}
	
	public static void main(String[] args) {
		System.err.println(getRandomNumber());
	}
}
